home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src-glu / tess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-12  |  7.5 KB  |  326 lines

  1. /* $Id: tess.c,v 1.3 1996/11/12 01:23:02 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.0
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: tess.c,v $
  26.  * Revision 1.3  1996/11/12 01:23:02  brianp
  27.  * added test to prevent free(vertex) when vertex==NULL in delete_contours()
  28.  *
  29.  * Revision 1.2  1996/10/22 22:57:19  brianp
  30.  * better error handling in gluBegin/EndPolygon() from Erich Eder
  31.  *
  32.  * Revision 1.1  1996/09/27 01:19:39  brianp
  33.  * Initial revision
  34.  *
  35.  */
  36.  
  37.  
  38. /*
  39.  * This file is part of the polygon tesselation code contributed by
  40.  * Bogdan Sikorski
  41.  */
  42.  
  43.  
  44. #include <math.h>
  45. #include <stdlib.h>
  46. #include "tess.h"
  47.  
  48.  
  49.  
  50. extern void tess_test_polygon(GLUtriangulatorObj *);
  51. extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
  52. extern void tess_handle_holes(GLUtriangulatorObj *);
  53. extern void tess_tesselate(GLUtriangulatorObj *);
  54. extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
  55. static void delete_contours(GLUtriangulatorObj *);
  56.  
  57. void init_callbacks(tess_callbacks *callbacks)
  58. {
  59.    callbacks->begin = ( void (*)(GLenum) ) 0;
  60.    callbacks->edgeFlag = ( void (*)(GLboolean) ) 0;
  61.    callbacks->vertex = ( void (*)(void*) ) 0;
  62.    callbacks->end = ( void (*)(void) ) 0;
  63.    callbacks->error = ( void (*)(GLenum) ) 0;
  64. }
  65.  
  66. void tess_call_user_error(GLUtriangulatorObj *tobj,
  67.     GLenum gluerr)
  68. {
  69.     if(tobj->error==GLU_NO_ERROR)
  70.         tobj->error=gluerr;
  71.     if(tobj->callbacks.error!=NULL)
  72.         (tobj->callbacks.error)(gluerr);
  73. }
  74.  
  75. GLUtriangulatorObj* gluNewTess( void )
  76. {
  77.    GLUtriangulatorObj *tobj;
  78.  
  79.     if((tobj=(GLUtriangulatorObj *)
  80.         malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
  81.         return NULL;
  82.     tobj->contours=tobj->last_contour=NULL;
  83.     init_callbacks(&tobj->callbacks);
  84.     tobj->error=GLU_NO_ERROR;
  85.     tobj->current_polygon=NULL;
  86.     tobj->contour_cnt=0;
  87.     return tobj;
  88. }
  89.  
  90.  
  91. void gluTessCallback( GLUtriangulatorObj *tobj, GLenum which,
  92.               void (*fn)() )
  93. {
  94.     switch(which)
  95.     {
  96.         case GLU_BEGIN:
  97.             tobj->callbacks.begin = (void (*)(GLenum)) fn;
  98.             break;
  99.         case GLU_EDGE_FLAG:
  100.             tobj->callbacks.edgeFlag = (void (*)(GLboolean)) fn;
  101.             break;
  102.         case GLU_VERTEX:
  103.             tobj->callbacks.vertex = (void (*)(void *)) fn;
  104.             break;
  105.         case GLU_END:
  106.             tobj->callbacks.end=fn = (void (*)(void)) fn;
  107.             break;
  108.         case GLU_ERROR:
  109.             tobj->callbacks.error = (void (*)(GLenum)) fn;
  110.             break;
  111.         default:
  112.             tobj->error=GLU_INVALID_ENUM;
  113.             break;
  114.     }
  115. }
  116.  
  117.  
  118.  
  119. void gluDeleteTess( GLUtriangulatorObj *tobj )
  120. {
  121.     if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
  122.         /* was gluEndPolygon called? */
  123.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  124.     /* delete all internal structures */
  125.     delete_contours(tobj);
  126.     free(tobj);
  127. }
  128.  
  129.  
  130. void gluBeginPolygon( GLUtriangulatorObj *tobj )
  131. {
  132. /*
  133.     if(tobj->error!=GLU_NO_ERROR)
  134.         return;
  135. */
  136.         tobj->error = GLU_NO_ERROR;
  137.     if(tobj->current_polygon!=NULL)
  138.     {
  139.         /* gluEndPolygon was not called */
  140.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  141.         /* delete all internal structures */
  142.         delete_contours(tobj);
  143.     }
  144.     else
  145.     {
  146.         if((tobj->current_polygon=
  147.             (tess_polygon *)malloc(sizeof(tess_polygon)))==NULL)
  148.         {
  149.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  150.             return;
  151.         }
  152.         tobj->current_polygon->vertex_cnt=0;
  153.         tobj->current_polygon->vertices=
  154.             tobj->current_polygon->last_vertex=NULL;
  155.     }
  156. }
  157.  
  158.  
  159. void gluEndPolygon( GLUtriangulatorObj *tobj )
  160. {
  161.     /*tess_contour *contour_ptr;*/
  162.  
  163.     /* there was an error */
  164.     if(tobj->error!=GLU_NO_ERROR) goto end;
  165.  
  166.     /* check if gluBeginPolygon was called */
  167.     if(tobj->current_polygon==NULL)
  168.     {
  169.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  170.         return;
  171.     }
  172.     tess_test_polygon(tobj);
  173.     /* there was an error */
  174.     if(tobj->error!=GLU_NO_ERROR) goto end;
  175.  
  176.     /* any real contours? */
  177.     if(tobj->contour_cnt==0)
  178.     {
  179.         /* delete all internal structures */
  180.         delete_contours(tobj);
  181.         return;
  182.     }
  183.     tess_find_contour_hierarchies(tobj);
  184.     /* there was an error */
  185.     if(tobj->error!=GLU_NO_ERROR) goto end;
  186.  
  187.     tess_handle_holes(tobj);
  188.     /* there was an error */
  189.     if(tobj->error!=GLU_NO_ERROR) goto end;
  190.  
  191.     /* if no callbacks, nothing to do */
  192.     if(tobj->callbacks.begin!=NULL && tobj->callbacks.vertex!=NULL &&
  193.         tobj->callbacks.end!=NULL)
  194.     {
  195.         if(tobj->callbacks.edgeFlag==NULL)
  196.             tess_tesselate(tobj);
  197.         else
  198.             tess_tesselate_with_edge_flag(tobj);
  199.     }
  200.  
  201. end:
  202.     /* delete all internal structures */
  203.     delete_contours(tobj);
  204. }
  205.  
  206.  
  207. void gluNextContour( GLUtriangulatorObj *tobj, GLenum type )
  208. {
  209.     if(tobj->error!=GLU_NO_ERROR)
  210.         return;
  211.     if(tobj->current_polygon==NULL)
  212.     {
  213.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  214.         return;
  215.     }
  216.     /* first contour? */
  217.     if(tobj->current_polygon->vertex_cnt)
  218.         tess_test_polygon(tobj);
  219. }
  220.  
  221.  
  222. void gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data )
  223. {
  224.     tess_polygon *polygon=tobj->current_polygon;
  225.     tess_vertex *last_vertex_ptr;
  226.  
  227.     if(tobj->error!=GLU_NO_ERROR)
  228.         return;
  229.     if(polygon==NULL)
  230.     {
  231.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  232.         return;
  233.     }
  234.     last_vertex_ptr=polygon->last_vertex;
  235.     if(last_vertex_ptr==NULL)
  236.     {
  237.         if((last_vertex_ptr=(tess_vertex *)
  238.             malloc(sizeof(tess_vertex)))==NULL)
  239.         {
  240.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  241.             return;
  242.         }
  243.         polygon->vertices=last_vertex_ptr;
  244.         polygon->last_vertex=last_vertex_ptr;
  245.         last_vertex_ptr->data=data;
  246.         last_vertex_ptr->location[0]=v[0];
  247.         last_vertex_ptr->location[1]=v[1];
  248.         last_vertex_ptr->location[2]=v[2];
  249.         last_vertex_ptr->next=NULL;
  250.         last_vertex_ptr->previous=NULL;
  251.         ++(polygon->vertex_cnt);
  252.     }
  253.     else
  254.     {
  255.         tess_vertex *vertex_ptr;
  256.  
  257.         /* same point twice? */
  258.         if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
  259.             fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
  260.             fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
  261.         {
  262.             tess_call_user_error(tobj,GLU_TESS_ERROR6);
  263.             return;
  264.         }
  265.         if((vertex_ptr=(tess_vertex *)
  266.             malloc(sizeof(tess_vertex)))==NULL)
  267.         {
  268.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  269.             return;
  270.         }
  271.         vertex_ptr->data=data;
  272.         vertex_ptr->location[0]=v[0];
  273.         vertex_ptr->location[1]=v[1];
  274.         vertex_ptr->location[2]=v[2];
  275.         vertex_ptr->next=NULL;
  276.         vertex_ptr->previous=last_vertex_ptr;
  277.         ++(polygon->vertex_cnt);
  278.         last_vertex_ptr->next=vertex_ptr;
  279.         polygon->last_vertex=vertex_ptr;
  280.     }
  281. }
  282.  
  283.  
  284. static void delete_contours(GLUtriangulatorObj *tobj)
  285. {
  286.     tess_polygon *polygon=tobj->current_polygon;
  287.     tess_contour *contour,*contour_tmp;
  288.     tess_vertex *vertex,*vertex_tmp;
  289.  
  290.     /* remove current_polygon list - if exists due to detected error */
  291.     if(polygon!=NULL)
  292.     {
  293.         if (polygon->vertices)
  294.         {
  295.             for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
  296.             {
  297.                 vertex_tmp=vertex->next;
  298.                 free(vertex);
  299.                 vertex=vertex_tmp;
  300.             }
  301.             free(vertex);
  302.         }
  303.         free(polygon);
  304.         tobj->current_polygon=NULL;
  305.     }
  306.     /* remove all contour data */
  307.     for(contour=tobj->contours;contour!=NULL;)
  308.     {
  309.         for(vertex=contour->vertices;vertex!=contour->last_vertex;)
  310.         {
  311.             vertex_tmp=vertex->next;
  312.             free(vertex);
  313.             vertex=vertex_tmp;
  314.         }
  315.         free(vertex);
  316.         contour_tmp=contour->next;
  317.         free(contour);
  318.         contour=contour_tmp;
  319.     }
  320.     tobj->contours=tobj->last_contour=NULL;
  321.     tobj->contour_cnt=0;
  322. }
  323.  
  324.  
  325.  
  326.